spb/autoscholar
Public
1"use client";2import { useRouter } from "next/navigation";3import { useState } from "react";4import { useToast } from "@/components/Toast";5import { type ApiError, api } from "@/lib/client/api";67export function RunActions({8 runId,9 status,10 paperId,11}: {12 runId: string;13 status: string;14 paperId: string | null;15}) {16 const router = useRouter();17 const toast = useToast();18 const [busy, setBusy] = useState(false);19 const act = async (path: string, body: unknown, ok: string) => {20 setBusy(true);21 try {22 await api(path, { json: body });23 toast.push("success", ok);24 router.refresh();25 } catch (e) {26 toast.push("error", (e as ApiError).message);27 } finally {28 setBusy(false);29 }30 };31 const canCancel = !["published", "cancelled", "failed", "cancelling"].includes(status);32 const canRetry = ["failed", "quality_failed"].includes(status);33 const canPublish = ["awaiting_approval", "ready_to_publish"].includes(status);34 return (35 <div className="flex flex-wrap gap-2">36 {canPublish && (37 <button38 type="button"39 className="btn btn-primary"40 disabled={busy}41 onClick={() =>42 confirm("Publish this run as a public working paper?") &&43 act("/api/admin/publications", { runId }, "Publication started.")44 }45 >46 Publish47 </button>48 )}49 {canRetry && (50 <button51 type="button"52 className="btn"53 disabled={busy}54 onClick={() => act(`/api/admin/runs/${runId}/retry`, {}, "Retry queued from the last checkpoint.")}55 >56 Retry from checkpoint57 </button>58 )}59 {canCancel && (60 <button61 type="button"62 className="btn btn-danger"63 disabled={busy}64 onClick={() =>65 confirm("Cancel this run? Logs and the frozen input are preserved.") &&66 act(`/api/admin/runs/${runId}/cancel`, {}, "Cancellation requested.")67 }68 >69 Cancel70 </button>71 )}72 {paperId && (73 <a className="btn" href="/admin/publications">74 Published paper75 </a>76 )}77 </div>78 );79}80